import time

from flask import request, json, session, g, render_template
from utils.captcha import CaptchaTool
from utils.token import create_token, check_token as c_t
from utils.common import response_error, response_other, response_get, get_body_data
from databases import HandleDb, db_configs

# 哪些url的请求 检查token
url_check_tokens = [
    {
        "url": "user_upload",
        "methods": ['POST']
    },
    {
        "url": "user_upload",
        "methods": ['GET', 'POST']
    },
]


def check_token():
    url = request.url
    method = request.method
    is_check = False
    for item in url_check_tokens:
        if url.find(item['url']) != -1:
            # 如果访问的url和method 在这个数组里,则跳过检查。
            if method in item['methods']:
                is_check = True

    # 为真则检查
    if is_check:
        token = request.headers.get('token')
        if not token:
            return response_error(401, "not token!")
        result = c_t(token)
        if not result:
            return response_error(401, "token error!")
        if result == 'error':
            return response_error(500)
        if result['username'] != session.get('username'):
            return response_error(401, "token error!")
        if result['exp'] < time.time():
            return response_error(401, "token已过期!")
    # 每次请求初始化数据库
    g.db_1 = HandleDb(**db_configs.LOCALHOST_DB_FLASK_DEMO_CONFIG)
    g.db_2 = HandleDb(**db_configs.LOCALHOST_DB_GALLERY_CONFIG)


def after_request_func(response):
    # 当请求响应以后,并且没有错误,才会走这里
    # 释放数据库资源
    if g.get('db_1'):
        g.db_1.close()
    if g.get('db_2'):
        g.db_2.close()
    return response


# 登录
def login():
    json_str = request.get_data()
    if not json_str:
        return response_error()
    body_data = json.loads(json_str)
    username = body_data.get('username')
    password = body_data.get('password')
    img_code = body_data.get('img_code')
    if not img_code or not username or not password:
        return response_error()
    # 检查验证码
    img_code1 = session.get("img_code")
    if img_code1 != img_code:
        return response_error(400, "验证码错误!")
    users: list[dict] = g.db_1.find('user', 'name,password,id', f'name = "{username}"')
    if users == 'error':
        return response_error(500)
    if not len(users):
        return response_error(402, "请注册!")
    if users[0].get('password') != password:
        return response_error(400, "用户名或密码错误!")
    token = create_token(username)
    session.setdefault('username', username)
    return response_get(200, {"id": users[0].get('id'), "token": token}, "success!")


# 注册
def register():
    json_str = request.get_data()
    if not json_str:
        return response_error()
    body_data = json.loads(json_str)
    username = body_data.get('username')
    password = body_data.get('password')
    img_code = body_data.get('img_code')
    # 检查验证码
    img_code1 = session.get("img_code")
    if img_code1 != img_code:
        return response_error(400, "验证码错误!")
    users: list[dict] = g.db_1.find('user', 'name', f'name = "{username}"')
    if users == 'error':
        return response_error(500)
    if len(users):
        return response_error(402, "此账号已被占用!")
    # 添加
    result = g.db_1.add('user', {"name": username, "password": password})
    if result == 'error':
        return response_error(500)
    return response_other(200, "注册成功!")


# 图片验证码
def code():
    capt_obj = CaptchaTool()
    img, code_text = capt_obj.get_verify_code()
    session['img_code'] = code_text
    return img


# 用户信息
def user(id):
    method = request.method
    if method == 'GET':
        if not id:
            return response_error()
        users = g.db_1.find('user', '*', f'id = {id}')
        if not len(users):
            return response_error(400, "找不到用户!")
        users[0].pop('password')
        return response_get(200, users[0])
    # 修改用户信息
    elif method == 'PUT':
        pass


# 获取首页频道
def index_channel():
    result = g.db_1.find('a_home')
    if result != 'error':
        return response_get(200, result)
    else:
        return response_error()


# 获取频道分类列表
def channel_category(channel_id):
    result = g.db_1.find('category', '*', f'channel_id = {channel_id}')
    result1 = g.db_1.find('channel', 'title', f'id = {channel_id}')
    if type(result) == list:
        return response_get(data={"data": result, "channel_title": result1[0]['title']})
    else:
        return response_get()


# 获取书的信息(一个或多个)
def book_list():
    json_str = request.get_data()
    body_data = json.loads(json_str)
    if 'id' in body_data:
        id_ = body_data.pop('id')
        ids_ = id_
        if isinstance(id_, int):
            ids_ = [id_]
        if isinstance(id_, list):
            str_or_where = ''
            for id_ in ids_:
                str_or_where += f'book.id = {id_} or '
            str_or_where = str_or_where[:-4]
            sql = f"select book.*,category.name as category_name from book inner join " \
                  f"category on category.id = category_id and"
            result = g.db_1.sql(sql + f" ({str_or_where})")
            if isinstance(result, list):
                return response_get(data=result)
            else:
                return response_get()

    return response_error()


# 上传头像
def upload_user_avatar():
    method = request.method
    if method == 'GET':
        return render_template('upload.html')
    else:
        file = request.files.get('file')
        # user_id = request.files.get('id')
        user_id = request.form.get('id')
        print(request.files)
        if user_id and file:
            result = g.db_1.find('user', '*', f'id = {user_id}')
            if type(result) == list and len(result):
                file_path = f'/front/static/user_avatar/{file.filename}'
                file.save('./blueprints' + file_path)
                result = g.db_1.update('user', {"avatar_url": file_path}, f'id = {user_id}')
                if result != 'error':
                    return response_get(200, data={"user_avatar_url": file_path})
            else:
                return response_error(err_msg='User not found')
        return response_error()
